package discover

import (
	"encoding/hex"
	"net"
	"strings"
	"time"

	"gitee.com/wulalade/hwpack/completion"
	"gitee.com/wulalade/hwpack/convert"
	"gitee.com/wulalade/hwpack/loglog"
	"gitee.com/wulalade/hwpack/utils"
)

type DeviceDiscover struct {
	DeviceName [16]byte
	HwVersion  [3]byte
	FwVersion  [3]byte
	Ip         [4]byte
	Port       [2]byte
	Mask       [4]byte
	Gateway    [4]byte
	Mac        [6]byte
}

var (
	Device   DeviceDiscover
	find_now chan struct{}
	eth_name string
)

// 应答发现
func rspUdp(udp_addr *net.UDPAddr, wMsg []byte) {
	udp_write_conn, err := net.DialUDP("udp", nil, udp_addr)
	if err != nil {
		loglog.Handler.Info("udp_write_conn:%s", err.Error())
	}
	defer udp_write_conn.Close()

	udp_write_conn.Write(wMsg)
}

func rspUdpDeviceMsg(udp_addr *net.UDPAddr) {
	devicePara := []byte{0xD1, 0x00, 0x39,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //设备名称，最大16 3:
		0x00, 0x00, 0x01, //硬件版本号 3  19:
		0x00, 0x00, 0x22, //软件版本号 3  22:
		0xC0, 0xA8, 0x0E, 0xAB, //ip地址 4  25:
		0x01, 0xF6, //端口号 2 29:
		0xFF, 0xFF, 0xFF, 0x00, //mask 4 31:
		0xC0, 0xA8, 0x0E, 0x01, //网关 4 35:
		0x00, 0x08, 0xDC, 0x11, 0x11, 0x11, //mac地址 6 39:
		0x02,                   //最大连接数 无用 1 45
		0xC0, 0xA8, 0x0E, 0xAF, //上传地址 无用 4 46
		0x17, 0x70, //上传端口 无用
		0x07, 0xD0, //重试时间 无用
		0x08,       //重试次数 无用
		0x0B, 0xB8, //上报间隔 无用
		0x00, //设备上传数据启用/停止标志（此处为停用） 无用
		0x00, //设备升级服务启用/停用标志（此处为停用） 无用
		0x1D}
	copy(devicePara[3:], Device.DeviceName[0:16])        //名称
	copy(devicePara[19:], Device.HwVersion[0:3])         //硬件版本号
	copy(devicePara[22:], Device.FwVersion[0:3])         //软件版本号
	copy(devicePara[25:], utils.GetEthIpByte(eth_name))  //ip
	copy(devicePara[29:], Device.Port[0:2])              //port
	copy(devicePara[31:], Device.Mask[0:4])              //mask地址
	copy(devicePara[35:], Device.Gateway[0:4])           //gateway地址
	copy(devicePara[39:], utils.GetEthMacByte(eth_name)) //mac地址

	rspUdp(udp_addr, devicePara)
}

// 开始运行
func Run(lan string, force bool) {
	eth_name = lan
	udp_addr, err := net.ResolveUDPAddr("udp", "224.0.0.8:9201")
	if err != nil {
		loglog.Handler.Info("discover ResolveUDPAddr:%s", err.Error())
	}
	var ifi *net.Interface
	if !force {
		*ifi, err = utils.GetInterfaces(eth_name)
		if err != nil {
			loglog.Handler.Info("discover GetInterfaces:%s", err.Error())
			return
		}
	}
	udp_conn, err := net.ListenMulticastUDP("udp", ifi, udp_addr)
	if err != nil {
		loglog.Handler.Info("discover %s ListenMulticastUDP:%s", eth_name, err.Error())
		return
	}
	//延迟关闭监听
	defer udp_conn.Close()

	udp_conn.SetWriteBuffer(1024)
	find_now = make(chan struct{}, 1)
	buf := make([]byte, 1024)
	go func() {
		sendDuration := time.Hour
		sendDelay := time.NewTimer(time.Second)
		defer sendDelay.Stop()

		for {
			select {
			case <-sendDelay.C:
				sendDelay.Reset(sendDuration)
				udp_conn.WriteToUDP([]byte{0xd0, 0x00, 0x0d}, udp_addr)
			case <-find_now:
				sendDelay.Reset(sendDuration)
				udp_conn.WriteToUDP([]byte{0xd0, 0x00, 0x0d}, udp_addr)
			}
		}
	}()

	for {
		//阻塞获取数据
		n, rec_addr, err := udp_conn.ReadFromUDP(buf[0:])
		if err == nil {
			//fmt.Println("ReadFromUDP : ", buf[0:n])
			if n == 3 {
				if buf[0] == 0xd0 && buf[1] == 0 && buf[2] == 0x0d {
					//fmt.Println("udp search device")
					loglog.Handler.Info("discover udp search device")
					rspUdpDeviceMsg(udp_addr)
				}
			} else {
				loglog.Handler.Info("discover found [%s] , len[%d] : %0x", rec_addr.IP, n, buf[0:n])
				if n == 60 {
					loglog.Handler.Info("DeviceName : %s", completion.StrRmNull(string(buf[3:19])))
					loglog.Handler.Info("HwVersion : %s", hex.EncodeToString(buf[19:22]))
					loglog.Handler.Info("FwVersion : %s", hex.EncodeToString(buf[22:25]))
					loglog.Handler.Info("IP : %d.%d.%d.%d", buf[25], buf[26], buf[27], buf[28])
					loglog.Handler.Info("PORT : %d", convert.BytesToUint16(buf[29:31]))
					loglog.Handler.Info("MASK : %d.%d.%d.%d", buf[31], buf[32], buf[33], buf[34])
					loglog.Handler.Info("GATEWAY : %d.%d.%d.%d", buf[35], buf[36], buf[37], buf[38])
					loglog.Handler.Info("MAC : %s\n", hex.EncodeToString(buf[39:45]))
				}
			}
		}
	}
}

// 立即查询
func RightNowFind() {
	if find_now != nil && len(find_now) < 1 {
		find_now <- struct{}{}
	}
}

// 设置设备名字
func SetDeviceName(deviceName string) {
	copy(Device.DeviceName[0:], completion.ByteCompletion([]byte(deviceName), len(Device.DeviceName)))
}

// 设置硬件版本
func SetHwVersion(hw_version string) {
	//删除所有的.
	hw := strings.ReplaceAll(hw_version, ".", "")
	hwbyte, err := hex.DecodeString(hw)
	if err == nil {
		copy(Device.HwVersion[0:], completion.ByteCompletion((hwbyte), len(Device.HwVersion)))
	}
}

// 设置软件版本
func SetFwVersion(fw_version string) {
	//删除所有的.
	fw := strings.ReplaceAll(fw_version, ".", "")
	fwbyte, err := hex.DecodeString(fw)
	if err == nil {
		copy(Device.FwVersion[0:], completion.ByteCompletion((fwbyte), len(Device.FwVersion)))
	}
}

// 设置端口号
func SetPort(port uint16) {
	//fmt.Printf("%d,%02x\n", port, convert.Uint16ToBytes(port))
	copy(Device.Port[0:], convert.Uint16ToBytes(port))
}

// 设置子网掩码
func SetMask(mask string) {
	maskByte := net.ParseIP(mask)
	if maskByte != nil {
		copy(Device.Mask[0:], completion.ByteCompletion((maskByte.To4()), len(Device.Mask)))
	}
}

// 设置网关
func SetGateway(gateway string) {
	gatewayByte := net.ParseIP(gateway)
	if gatewayByte != nil {
		copy(Device.Gateway[0:], completion.ByteCompletion((gatewayByte.To4()), len(Device.Gateway)))
	}
}
